﻿#light

open UserLexer
open Tokens

let ExecWithTimeMeasure proc = 
    let time' = System.DateTime.UtcNow
    let result = proc ()
    let time'' = System.DateTime.UtcNow
    result, time'' - time'
    
let testPath = @"..\.."
let testFile = "test.in"
let content = System.IO.File.ReadAllText(testPath + "\\" + testFile)      

         
let test1 () = 
    let lexems = run_string content
    Seq.iter (printfn "%A\n") lexems
    printf "%d\n" LinesLexer.linecount
    Seq.length lexems

let test2 () = 
    let lexems = Seq.toList <| run_string content        
    printf "%d\n" LinesLexer.linecount
    lexems.Length
    
let runTest i test = 
    let (r,t) = ExecWithTimeMeasure test 
    printf "Test #%d\n Tokens count:%d\n Execution time(msec):%.3f\n" i r t.TotalMilliseconds 
  
// do not run this tests in single program run to get precise results  
//runTest 1 test1
//runTest 2 test2



// code below demonstrates using interfaces, classes, defining properties, etc.
type ITokenSeqFilter = interface    
    abstract member Filtered: seq<Tokens.Tokens> 
    end

type CountingFilter(tkns:seq<Tokens.Tokens>) = class 
    let linesCnt = ref 1
    let sharpLinesCnt = ref 0
    let tknCnt = ref 0
    let whiteCnt = ref 0
    let mutable whiteLen = 0
    member x.Lines = !linesCnt
    member x.SharpLines = !sharpLinesCnt
    member x.Tokens = !tknCnt
    member x.Whitespaces = !whiteCnt
    member x.WhitespacesTotal = whiteLen
    member x.Filtered = seq { 
        for token in tkns do
            incr tknCnt
            match token with 
             | NEW_LINE _ -> incr linesCnt
             | SHARP_LINE _ -> incr sharpLinesCnt
             | WHITE s -> incr whiteCnt; whiteLen <- whiteLen + s.Length
             | _ -> () // ignore
            yield token 
         done            
       }

    interface ITokenSeqFilter with
      member x.Filtered = x.Filtered // not a bug! Means 'Use CountingFilter.Filtered to implement ITokenSeqFilter.Filtered'
end
let filter = new CountingFilter(run_string content)
runTest 3  (fun () -> (Seq.toList (filter:>ITokenSeqFilter).Filtered).Length) // Data are accessed via interface ITokenSeqFilter
printf "Counters\n\tLines:%d\n\tSharpLines:%d\n\tTokens:%d\n\tWhitespaces:%d\n\tWhatespaces(total chars):%d\n" 
        filter.Lines filter.SharpLines filter.Tokens filter.Whitespaces filter.WhitespacesTotal
  
